package simulatorUS;

import java.awt.Container;
import java.awt.EventQueue;
import java.awt.Panel;

import javax.swing.JFrame;
import net.miginfocom.swing.MigLayout;

import javax.swing.ButtonModel;
import javax.swing.JSplitPane;
import javax.swing.JPanel;
import javax.swing.JButton;
import javax.swing.JRadioButton;
import javax.swing.JRadioButtonMenuItem;
import javax.swing.ButtonGroup;
import javax.swing.JToggleButton;
import javax.swing.JTree;
import javax.swing.JScrollPane;
import javax.swing.JTextPane;
import javax.swing.border.TitledBorder;

import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import javax.swing.JComboBox;
import javax.swing.JTextField;
import java.awt.Color;
import javax.swing.JLabel;
import javax.swing.JCheckBox;
import javax.swing.JTextArea;
import java.awt.Component;
import java.util.Calendar;
import java.util.Formatter;
import java.util.Iterator;
import java.util.Map.Entry;
import java.util.Set;

import javax.swing.Box;
import java.awt.Font;
import java.awt.Dimension;
import javax.swing.DropMode;

public class MainFrame extends JFrame implements SystemCommandExecutor,
		SystemEventGenerator {
	private final int MAX_PARAM_CHAR_NUM = 3;
	private ButtonGroup modeBtnGroup = new ButtonGroup();

	JFrame frmUltrasonicDoubleBill;
	private int lastSelectedParamIndex;
	private JTextField paramValtextField;

	private SystemEventHandler SystemEventHandler;

	private static JTextArea commTextArea;

	private JPanel commandPanel;
	private SystemEvent lastEvent;

	private JButton btnConn;

	private JButton btnStopall;

	private JButton btnQparam;

	private JButton btnStatus;

	private JButton btnVersion;

	private JButton btnStartcm;

	private JButton btnStartvcm;

	private JButton btnBit;

	private JButton btnSparam;

	private JComboBox paramSelector;

	private JPanel sparampanel;

	private JButton btnSelfcal;
	private JButton btnDbill;
	private JPanel panel;
	private JCheckBox checkBoxDispCommData;
	private boolean enableCommData;
	private String tempStr = "";
	private char sensMode = CommandsMCU.ONE_SHOT_MODE;
	private JButton btnACK;

	/**
	 * Create the application.
	 */
	public MainFrame() {
		initialize();
	}

	/**
	 * Initialize the contents of the frame.
	 */
	private void initialize() {
		frmUltrasonicDoubleBill = new JFrame();
		frmUltrasonicDoubleBill.setMinimumSize(new Dimension(900, 600));
		frmUltrasonicDoubleBill
				.setTitle("Ultrasonic double bill sensor simulator V4");
		frmUltrasonicDoubleBill.setBounds(100, 100, 900, 530);
		frmUltrasonicDoubleBill.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		frmUltrasonicDoubleBill.getContentPane().setLayout(
				new MigLayout("", "[grow]",
						"[577.00,grow][-14.00][11.00][11.00]"));

		JSplitPane splitPane = new JSplitPane();
		splitPane.setEnabled(false);
		splitPane.setContinuousLayout(true);
		frmUltrasonicDoubleBill.getContentPane()
				.add(splitPane, "cell 0 0,grow");

		JPanel controlElpanel = new JPanel();
		controlElpanel.setMinimumSize(new Dimension(150, 10));
		splitPane.setLeftComponent(controlElpanel);
		controlElpanel.setLayout(new MigLayout("", "[240.00]",
				"[][10.00][334.00][]"));

		panel = new JPanel();
		controlElpanel.add(panel, "cell 0 0,grow");
		panel.setLayout(new MigLayout("", "[240.00]", "[]"));
		btnConn = new JButton("Find sensor board");
		panel.add(btnConn, "cell 0 0,growx");
		btnConn.setToolTipText("Find device port");
		btnConn.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				commTextArea.append("<-" + arg0.getActionCommand()
						+ (getSysTime()) + "\n");
				lastEvent = new SystemEvent(this, SensEventID.CONN_PRESSED);
				generateEvent(lastEvent);
				btnStartcm.setEnabled(true);
				btnStartvcm.setEnabled(true);
				btnStopall.setEnabled(false);
				lastSelectedParamIndex = 0;
				sensMode = CommandsMCU.ONE_SHOT_MODE;

				// String portName = uart.findDevicePort("1\r\n", "1 0\r\n",
				// 250);
				// if (portName != null) {
				// commTextArea.append("Device was found on port " + portName
				// + "\n");
				// setComponentsOnPanelEnable(commandPanel, true);
				// } else
				// {
				// commTextArea.append("Device wasn't found!\n");
				// setComponentsOnPanelEnable(commandPanel, false);
			}
			// }
		});

		Component verticalStrut = Box.createVerticalStrut(20);
		controlElpanel.add(verticalStrut, "cell 0 1");

		commandPanel = new JPanel();
		controlElpanel.add(commandPanel, "cell 0 2,grow");
		commandPanel.setLayout(new MigLayout("", "[239.00]",
				"[][][][][][][][][][][][][][-10.00][][-12.00][47.00]"));
		btnBit = new JButton("BIT");
		btnBit.setToolTipText("Built in test ");
		commandPanel.add(btnBit, "cell 0 0,grow");
		btnBit.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				// btnStartcm.setEnabled(false);
				// btnStartvcm.setEnabled(false);
				btnStopall.setEnabled(false);

				tempStr = "";
				if (enableCommData)
					tempStr = "<- "
							+ toHexFormat(String.valueOf(CommandsMCU.BIT_COMM
									+ CommandsMCU.USART_MESSAGE_ENDING)) + "\n";
				commTextArea.append(tempStr + "<-" + arg0.getActionCommand()
						+ (getSysTime()) + "\n");
				lastEvent = new SystemEvent(this, SensEventID.BIT_PRESSED);
				generateEvent(lastEvent);
			}
		});

		btnSelfcal = new JButton("SELFCAL");
		btnSelfcal.setToolTipText("Self calibration");
		btnSelfcal.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {

				tempStr = "";
				if (enableCommData)
					tempStr = "<- "
							+ toHexFormat(String
									.valueOf(CommandsMCU.SELFCAL_COMM
											+ CommandsMCU.USART_MESSAGE_ENDING))
							+ "\n";
				commTextArea.append(tempStr + "<-" + arg0.getActionCommand()
						+ (getSysTime()) + "\n");
				lastEvent = new SystemEvent(this, SensEventID.SELFCAL_PRESSED);
				generateEvent(lastEvent);
			}
		});
		commandPanel.add(btnSelfcal, "cell 0 1,grow");

		btnDbill = new JButton("DBILL");
		btnDbill.setToolTipText("Single double bill detection");
		btnDbill.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				tempStr = "";
				if (enableCommData)
					tempStr = "<- "
							+ toHexFormat(String.valueOf(CommandsMCU.DBILL_COMM
									+ CommandsMCU.USART_MESSAGE_ENDING)) + "\n";
				commTextArea.append(tempStr + "<-" + arg0.getActionCommand()
						+ (getSysTime()) + "\n");

				lastEvent = new SystemEvent(this, SensEventID.DBILL_PRESSED);
				generateEvent(lastEvent);
			}
		});
		commandPanel.add(btnDbill, "cell 0 2,grow");

		sparampanel = new JPanel();
		commandPanel.add(sparampanel, "cell 0 3,growx");
		sparampanel.setLayout(new MigLayout("",
				"[189.00px,fill][42.00px,center]", "[23px][10px]"));

		btnSparam = new JButton("SPARAM");
		btnSparam.setToolTipText("Set parameter value");
		btnSparam.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				int paramValue = 0;
				String paramFiledStr = paramValtextField.getText();
				try {
					paramValue = Integer.valueOf(paramFiledStr);
					if (paramValue <= 255) {
						tempStr = "";
						if (enableCommData)
							tempStr = "<- "
									+ toHexFormat(String.valueOf(CommandsMCU.SPARAM_COMM
											+ " "
											+ String.valueOf(paramSelector
													.getSelectedIndex())
											+ " "
											+ String.valueOf(paramValue)
											+ CommandsMCU.USART_MESSAGE_ENDING))
									+ "\n";
						commTextArea.append(tempStr + "<-"
								+ e.getActionCommand() + (getSysTime()) + "\n");
						lastEvent = new SystemEvent(this,
								SensEventID.SPARAM_PRESSED, String
										.valueOf(paramSelector
												.getSelectedIndex()), String
										.valueOf(paramValue));
						generateEvent(lastEvent);
					} else {
						commTextArea
								.append("  Parameter value should be less than 256! Please try again.\n");

					}
				} catch (NumberFormatException ex) {
					commTextArea
							.append("  Incorrect number format! Please try again.\n");
				}
			}
		});
		sparampanel.add(btnSparam, "flowx,cell 0 0,grow");

		paramSelector = new JComboBox();
		// paramSelector.addItem(arg0)
		Set<Entry<Integer, String>> paramNameSet = USParam.paramNames
				.entrySet();
		Iterator<Entry<Integer, String>> it = paramNameSet.iterator();
		while (it.hasNext()) {
			String name = it.next().getValue();
			name = name.substring(0, 1) + name.substring(1).toLowerCase();
			paramSelector.addItem(name);
		}
		paramSelector.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				lastSelectedParamIndex = ((JComboBox) arg0.getSource())
						.getSelectedIndex();
			}
		});

		paramValtextField = new JTextField();
		paramValtextField.setForeground(Color.BLACK);
		paramValtextField.setFont(new Font("Arial", Font.BOLD, 18));
		paramValtextField.setToolTipText("Parameter value");
		paramValtextField.setDocument(new JTextFieldLimit(MAX_PARAM_CHAR_NUM,
				false, true));
		paramValtextField.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
			}
		});
		sparampanel.add(paramValtextField, "cell 1 0,grow");
		paramSelector.setToolTipText("Parameter selection");
		sparampanel.add(paramSelector, "cell 0 1 2 1,growx,aligny center");

		btnQparam = new JButton("QPARAM");
		btnQparam.setToolTipText("Query parameter list");
		btnQparam.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				tempStr = "";
				if (enableCommData)
					tempStr = "<- "
							+ toHexFormat(String
									.valueOf(CommandsMCU.QPARAM_COMM
											+ CommandsMCU.USART_MESSAGE_ENDING))
							+ "\n";
				commTextArea.append(tempStr + "<-" + arg0.getActionCommand()
						+ (getSysTime()) + "\n");
				lastEvent = new SystemEvent(this, SensEventID.QPARAM_PRESSED);
				generateEvent(lastEvent);
			}
		});
		commandPanel.add(btnQparam, "cell 0 4,grow");

		btnVersion = new JButton("VERSION");
		btnVersion.setToolTipText("Version request");
		btnVersion.addActionListener(new ActionListener() {

			public void actionPerformed(ActionEvent arg0) {
				tempStr = "";
				if (enableCommData)
					tempStr = "<- "
							+ toHexFormat(String
									.valueOf(CommandsMCU.VERSION_COMM
											+ CommandsMCU.USART_MESSAGE_ENDING))
							+ "\n";
				commTextArea.append(tempStr + "<-" + arg0.getActionCommand()
						+ (getSysTime()) + "\n");
				lastEvent = new SystemEvent(this, SensEventID.VERSION_PRESSED);
				generateEvent(lastEvent);
			}
		});
		commandPanel.add(btnVersion, "cell 0 5,grow");

		btnStatus = new JButton("STATUS");
		btnStatus.setToolTipText("Device status request");
		btnStatus.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				tempStr = "";
				if (enableCommData)
					tempStr = "<- "
							+ toHexFormat(String
									.valueOf(CommandsMCU.STATUS_COMM
											+ CommandsMCU.USART_MESSAGE_ENDING))
							+ "\n";
				commTextArea.append(tempStr + "<-" + arg0.getActionCommand()
						+ (getSysTime()) + "\n");
				lastEvent = new SystemEvent(this, SensEventID.STATUS_PRESSED);
				generateEvent(lastEvent);
			}
		});
		commandPanel.add(btnStatus, "cell 0 6,grow");

		btnStartcm = new JButton("START");
		btnStartcm
				.setToolTipText("Start double bill detection process in continuous mode");
		btnStartcm.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				setComponentsOnPanelEnable(commandPanel, false);
				btnBit.setEnabled(true);
				btnSparam.setEnabled(true);
				btnQparam.setEnabled(true);
				btnStatus.setEnabled(true);
				btnStopall.setEnabled(true);
				btnVersion.setEnabled(true);
				tempStr = "";
				if (enableCommData)
					tempStr = "<- "
							+ toHexFormat(String
									.valueOf(CommandsMCU.STARTCM_COMM
											+ CommandsMCU.USART_MESSAGE_ENDING))
							+ "\n";
				commTextArea.append(tempStr + "<-" + arg0.getActionCommand()
						+ (getSysTime()) + "\n");
				lastEvent = new SystemEvent(this, SensEventID.START_PRESSED);
				generateEvent(lastEvent);
			}
		});
		commandPanel.add(btnStartcm, "cell 0 7,grow");

		btnStartvcm = new JButton("START VOLATILE");
		btnStartvcm
				.setToolTipText("Start double bill detection process in voalatile continuous mode");
		btnStartvcm.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				setComponentsOnPanelEnable(commandPanel, false);
				btnBit.setEnabled(true);
				btnSparam.setEnabled(true);
				btnQparam.setEnabled(true);
				btnStatus.setEnabled(true);
				btnStopall.setEnabled(true);
				btnVersion.setEnabled(true);
				tempStr = "";
				if (enableCommData)
					tempStr = "<- "
							+ toHexFormat(String
									.valueOf(CommandsMCU.STARTVCM_COMM
											+ CommandsMCU.USART_MESSAGE_ENDING))
							+ "\n";
				commTextArea.append(tempStr + "<-" + arg0.getActionCommand()
						+ (getSysTime()) + "\n");
				lastEvent = new SystemEvent(this,
						SensEventID.START_VOLATILE_PRESSED);
				generateEvent(lastEvent);
			}
		});
		commandPanel.add(btnStartvcm, "cell 0 8,grow");

		btnStopall = new JButton("STOPALL");
		btnStopall.setToolTipText("Stop bill detection process");
		btnStopall.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				tempStr = "";
				if (enableCommData)
					tempStr = "<- "
							+ toHexFormat(String
									.valueOf(CommandsMCU.STOPALL_COMM
											+ CommandsMCU.USART_MESSAGE_ENDING))
							+ "\n";
				commTextArea.append(tempStr + "<-" + arg0.getActionCommand()
						+ (getSysTime()) + "\n");
				lastEvent = new SystemEvent(this, SensEventID.STOP_ALL_PRESSED);
				generateEvent(lastEvent);
				// btnStopall.setEnabled(false);
				btnBit.setEnabled(true);
				btnSelfcal.setEnabled(true);
				btnStartcm.setEnabled(true);
				btnStartvcm.setEnabled(true);
				btnDbill.setEnabled(true);
				btnACK.setEnabled(true);
				setComponentsOnPanelEnable(sparampanel, true);
			}
		});
		commandPanel.add(btnStopall, "cell 0 9,grow");

		JScrollPane scrollPane = new JScrollPane();
		splitPane.setRightComponent(scrollPane);

		commTextArea = new JTextArea();
		commTextArea.setRows(2);
		commTextArea.setLineWrap(true);
		commTextArea.setWrapStyleWord(true);
		commTextArea.setFont(new Font("Monospaced", Font.BOLD, 12));
		scrollPane.setViewportView(commTextArea);

		JButton btnClr = new JButton("Clear");
		btnClr.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				commTextArea.setText("");
			}
		});
		frmUltrasonicDoubleBill.getContentPane().add(btnClr,
				"cell 0 2,alignx right");
		setComponentsOnPanelEnable(commandPanel, false);

		btnACK = new JButton("ACK");
		btnACK.setToolTipText("Send ACK message");
		btnACK.setEnabled(false);
		btnACK.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				tempStr = "";
				if (enableCommData)
					tempStr = "<- " + toHexFormat(CommandsMCU.USART_MESSAGE_ENDING)+"\n";
				commTextArea.append(tempStr + "<-" + arg0.getActionCommand()
						+ (getSysTime()) + "\n");
				lastEvent = new SystemEvent(this, SensEventID.ACK_PRESSED);
				generateEvent(lastEvent);
			}
		});
		commandPanel.add(btnACK, "cell 0 10,growx");

		checkBoxDispCommData = new JCheckBox("Display communication data");
		checkBoxDispCommData.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				if (checkBoxDispCommData.isSelected()) {
					enableCommData = true;
					lastEvent = new SystemEvent(this,
							SensEventID.DISPLAY_COMM_DATA_ENABLED);

				} else {
					enableCommData = false;
					lastEvent = new SystemEvent(this,
							SensEventID.DISPLAY_COMM_DATA_DISABLED);
				}
				generateEvent(lastEvent);
			}
		});
		controlElpanel.add(checkBoxDispCommData, "cell 0 3");

	}

	protected String getSysTime() {
		Calendar cal = Calendar.getInstance();
		return new Formatter().format(" (%tT)", cal).toString();

	}

	private void setComponentsOnPanelEnable(JPanel comp, boolean setEnable) {
		for (Component c : comp.getComponents()) {
			if (c.getClass() == (JPanel.class)) {
				setComponentsOnPanelEnable((JPanel) c, setEnable);
			} else
				c.setEnabled(setEnable);
		}

	}

	@Override
	public void execute(SystemCommand command) {

		sensFrameCommandID commTitle = sensFrameCommandID.valueOf(command
				.getID());
		String commParams[] = command.getParams();
		switch (commTitle) {
		case ADD_TEXT:
			commTextArea.append(commParams[0] + "\n");
			break;
		case REINIT_FRAME:

			break;
		case ENABLE_COMMAND_PANEL:
			setComponentsOnPanelEnable(commandPanel, true);
			break;
		case DISABLE_COMMAND_PANEL:
			setComponentsOnPanelEnable(commandPanel, false);
			break;
		case STOP_ALL_BUTTON_ENABLE:
			btnStopall.setEnabled(true);
			break;
		case STOP_ALL_BUTTON_DISABLE:
			btnStopall.setEnabled(false);
			break;
		case Q_PARAM_BUTTON_ENABLE:
			btnQparam.setEnabled(true);
			break;
		case Q_PARAM_BUTTON_DISABLE:
			btnQparam.setEnabled(false);
			break;
		case STATUS_BUTTON_ENABLE:
			btnStatus.setEnabled(true);
			break;
		case STATUS_BUTTON_DISABLE:
			btnStatus.setEnabled(false);
			break;
		case VERSION_BUTTON_ENABLE:
			btnVersion.setEnabled(true);
			break;
		case VERSION_BUTTON_DISABLE:
			btnVersion.setEnabled(false);
			break;
		case START_BUTTON_ENABLE:
			btnStartcm.setEnabled(true);
			break;
		case START_BUTTON_DISABLE:
			btnStartcm.setEnabled(false);
			break;
		case START_VOLATILE_BUTTON_ENABLE:
			btnStartvcm.setEnabled(true);
			break;
		case START_VOLATILE_BUTTON_DISABLE:
			btnStartvcm.setEnabled(false);
			break;

		}
	}

	@Override
	public void generateEvent(SystemEvent event) {
		SystemEventHandler.eventOccured(event);

	}

	@Override
	public void SetSystemEventHandler(SystemEventHandler eventHandler) {
		SystemEventHandler = eventHandler;
	}

	public String toHexFormat(String str) {
		String resp = "";
		Formatter f = new Formatter();
		byte[] bytebuf = str.getBytes();
		for (Byte b : bytebuf) {

			f.format("0x%x ", b);
		}
		resp += f.toString().toUpperCase();
		resp = resp.replace('X', 'x');
		return resp;
	}

}
